#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <cassert>
#include <vector>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "Task.hpp"

#define PROCESS_NUM 5

using namespace std;

int waitCommand(int waitfd)
{
    u_int32_t command = 0;
    ssize_t s = read(waitfd, &command, sizeof(command));
    if(s==0)
    {
        exit(-1);
    }
    assert(s == sizeof(command));
    return command;
}

void sendAndWakeup(pid_t id,int fd,u_int32_t command)
{
    write(fd,&command,sizeof(command));
    cout<<"main process: call process "<<id<<" execute "<<desc[command]<<" through "<<fd<<endl;
}
int main()
{
    load();
    vector<pair<pid_t, int>> slots;
    for (int i = 0; i < PROCESS_NUM; i++)
    {
        int pipefd[2];
        int n = pipe(pipefd);
        assert(n == 0);
        (void)n;

        pid_t id = fork();
        if (id == 0)
        {
            // 子进程
            close(pipefd[1]);
            while (true)
            {
                int command = waitCommand(pipefd[0]);
                if (command >= 0 && command < handlerSize())
                {
                    callbacks[command]();
                }
                else
                {
                    cout << "非法command:" << command << endl;
                }
            }
            exit(0);
        }
        // 父进程
        close(pipefd[0]);
        slots.push_back(make_pair(id, pipefd[1])); // vector里面保存这个键值对，一个是子进程的pid，另一个是对应子进程与父进程管道的读端fd
    }

    srand((unsigned long)time(nullptr));

    int select;
    int command;
    while (true)
    {
        int command=rand()%handlerSize();
        int choice=rand()%slots.size();

        sendAndWakeup(slots[choice].first,slots[choice].second,command);
        sleep(1);
        // cout << "#######################################################" << endl;
        // cout << "#####    1. show function     2. send command     #####" << endl;
        // cout << "####################   3. exit    #####################" << endl;

        // cout << "Please enter your select> ";
        // cin >> select;
        // switch (select)
        // {
        // case 1:
        //     showHandler();
        //     break;
        // case 2:
        // {
        //     cout<<"Please enter your command> ";
        //     cin>>command;
        //     int choice = rand()%slots.size();
        //     sendAndWakeup(slots[choice].first,slots[choice].second,command);
        //     break;
        // }
        // case 3:
        //     break;
        // default:
        //     cout<<"非法输入"<<endl;
        //     break;
        // }
        // if(select==3)
        // {
        //     break;
        // }
        // sleep(1);
    }

    for(const auto& slot:slots)
    {
        close(slot.second);
    }

    for(const auto& slot:slots)
    {
        waitpid(slot.first,nullptr,0);
    }

    return 0;
}